home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / misc / amag / AM9403_2.lha / tips & tricks / wurzel.asm < prev    next >
Assembly Source File  |  1994-01-21  |  3KB  |  81 lines

  1. ; Dieses Programm berechnet die Wurzel eines
  2. ; 32-Bit-Unsigned-Integer-Ausdrucks (d.h. bis
  3. ; max. 4.294.967.295) per Intervallhalbierung.
  4. ; Ergebnis=SQRT(n) aufgerundet.
  5. ; Ein- und Ausgabe:
  6. ; d0    Eingabe, bleibt erhalten
  7. ; d1    obere Grenze des Intervalls = Ergebnis
  8. ; d2    untere Grenze des Intervalls
  9. ; d3,d4 Rechenregister
  10. ; a0    Zeiger auf Wertetabelle
  11.  
  12. exakt equ 1   ; Genauigkeit (zwischen 1 und 8)
  13.  
  14. SQRT:
  15.   movem.l d2-d4/a0,-(sp)  ; Register sichern
  16.   moveq   #0,d2   ; untere Grenze löschen
  17.   moveq   #0,d1   ; obere Grenze löschen
  18.   moveq   #30,d3  ; Bit-Zähler setzen
  19.   move.l  d0,d4   ; Wert in Rechenregister
  20.   beq.s   sqrt_6  ; n=0 -> keine Rechnung !
  21.   swap    d4      ; oberes Wort
  22.   tst.w   d4      ;  testen
  23.   bne.s   sqrt_11 ; Sprung, wenn <> 0
  24.   moveq   #14,d3  ; nur noch unteres Wort
  25.   move.w  d0,d4   ; untersuchen
  26. sqrt_11:
  27.   move.w  d4,d2   ; zu untersuchendes Wort merken
  28.   and.w   #$ff00,d4 ; oberen 8 Bit untersuchen
  29.   bne.s   sqrt_12   ; sind gesetzt -> Sprung
  30.   subq.w  #8,d3   ; 8 Bit weiter
  31.   move.w  d2,d4   ; Wort nochmal holen
  32.   lsl.w   #8,d4   ; unteren 8 Bit untersuchen
  33. sqrt_12:
  34.   asl.w   #1,d4   ; oberstes Bit suchen
  35.   dbcs    d3,sqrt_12  ; wenn CarrySet := gefunden
  36.  
  37.   add.w   d3,d3   ; * 2 := auf Wortgrenze legen
  38.                   ; Zeiger auf Werte berechnen
  39.   lea     sqrt_tab(pc,d3.w),a0
  40.   move.w  (a0)+,d2  ; untere Grenze holen
  41.   move.w  (a0),d1   ; obere Grenze holen
  42.   bra.s   sqrt_5    ; Ende erreicht?
  43. sqrt_2:
  44.   move.l  d2,d4   ; obere Grenze und
  45.   add.l   d1,d4   ; untere Grenze addieren
  46.   lsr.l   #1,d4   ; Mittelwert bilden: m=(og+ug)/2
  47.   move.l  d4,d3   ; m merken
  48.   mulu    d4,d4   ; m quadrieren
  49.   cmp.l   d0,d4   ; Test: Ist m*m > n ?
  50.   bgt.s   sqrt_4  ; ja -> springen
  51. sqrt_3:           ; obere Hälfte enthält
  52.                   ; gesuchten Wert
  53.   move.l  d3,d2   ; untere Grenze = m
  54.   bra.s   sqrt_5
  55. sqrt_4:           ; untere Hälfte enthält Wert
  56.   move.l  d3,d1   ; obere Grenze = m
  57. sqrt_5:
  58.   move.l  d1,d4   ; Differenz bestimmen
  59.   sub.l   d2,d4   ; delta = obere - untere Grenze
  60.   subq.w  #exakt,d4 ; delta = < exakt ? , Konstante
  61.                     ; bestimmt die Genauigkeit
  62.                   ; Differenz zu groß, weiterrechnen
  63.   bgt.s   sqrt_2
  64.   move.l  d2,d4
  65.   mulu    d4,d4   ; untere Grenze quadrieren
  66.   cmp.l   d4,d0   ; Vergleich mit n
  67.   bgt.s   sqrt_6  ; Test, ob untere Grenze das
  68.   move.l  d2,d1   ; Ergebnis ist
  69. sqrt_6:
  70.   movem.l (sp)+,d2-d4/a0  ; Register restaurieren
  71.   rts
  72.  
  73.   dc.w  0
  74. sqrt_tab:         ; Wurzel-Intervall-Grenzen | Bit
  75.  dc.w 1,2,3,4,6,8,12,16                      ; 0-7
  76.  dc.w 23,32,46,64,91,128,182,256             ; 8-15
  77.  dc.w 363,512,725,1024,1449,2048,2897,4096   ; 16-23
  78.                                              ; 24-31
  79.  dc.w 5793,8192,11586,16384,23171,32768,46341,65535
  80.  
  81.